/**
 * 
 */
package com.ideeli.webextractor.service;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;

import com.ideeli.webextractor.dao.ProductDao;
import com.ideeli.webextractor.domain.BlockAttributes;
import com.ideeli.webextractor.domain.Eb;
import com.ideeli.webextractor.domain.Product;

/**
 * @author sa
 *
 */
public class EbGenBlockServiceImpl implements EbGenBlockService
{
	
	private static final Logger logger = Logger.getLogger(EbGenBlockServiceImpl.class);
	
	private ProductDao productDao;
	
	private EbMappingService ebMappingService;
	
	private CacheService cacheService;


	/* (non-Javadoc)
	 * @see com.ideeli.webextractor.service.EbGenBlockService#generateEbBlock()
	 */
	@Override
	public void generateEbBlock() throws Exception
	{
		logger.warn("start generateEbBlock()");
		List<Eb> ebEntries= productDao.getEbEligEntries();
		
		mapITCategoriesToEb(ebEntries);

		List<List<Eb>> blocks= generateBlocks(ebEntries);
		
		for(List<Eb> block:blocks)
		{
			StringBuffer whrClsPIds= new StringBuffer(" (");
			for(Eb eb: block)
			{
				whrClsPIds.append(eb.getProdId());
				whrClsPIds.append(",");
			}
			whrClsPIds.deleteCharAt(whrClsPIds.length()-1);
			whrClsPIds.append(")");
			List<Product> products=productDao.getEbayProducts(whrClsPIds.toString());
			
			logger.warn("no of products in a block: "+products.size());
			if(products.size()<1)
				continue;
			
			ebMappingService.mapEbFields(products);
		}
		
		logger.warn("Finish generateEbBlock()");
	}

	/**
	 * Max 3 items per category in each block
	 * price limit for the block is 7500 
	 * @param ebEntries
	 * @return
	 */
	public List<List<Eb>> generateBlocks(List<Eb> ebEntries) 
	{
		logger.warn("start generateBlocks");
		LinkedList<Eb> ebLinkedList= new LinkedList<Eb>();
		List<List<Eb>> blocks=new ArrayList<List<Eb>>();
		
		ebLinkedList.addAll(ebEntries);
		
		sort(ebLinkedList);
		
		logger.warn("built linked list of EbEntries");		

		while(ebLinkedList.size()!=0)
		{
			logger.warn("ebLinkedList.size():"+ebLinkedList.size());
			List<Eb> block=new ArrayList<Eb>();
			List<Eb> removeList=new ArrayList<Eb>();
			BlockAttributes blockAttr=new BlockAttributes();
			
			for(Eb e: ebLinkedList)
			{
				float blkVal=e.getPrice()+blockAttr.getTotal();
				
				if(blkVal>7500)
					break;;

				boolean success=blockAttr.updateCategory(e.getEbCode());
				if(success)
				{
					//TODO find out how many null eb categories are null make them default cat to include items
					if(e.getEbCode()!=null)
						block.add(e);
					
					removeList.add(e);
					blockAttr.updateTotal(e.getPrice());
				}
			}
			
			ebLinkedList.removeAll(removeList);
			
			blocks.add(block);
		}
		logger.warn("Total blocks generated: "+blocks.size());
		
		logger.warn("end generateBlocks");
		return blocks;
	}

	//sort ascending on price so first file of the block will have more no of small value entries
	public void sort(List<Eb> ebLinkedList) 
	{
		
		for(int i=0;i<ebLinkedList.size();i++)
		{
			for(int j=i+1;j<ebLinkedList.size(); j++)
			{
				if(ebLinkedList.get(i).getPrice()>ebLinkedList.get(j).getPrice())	
				{
					Eb tmp=ebLinkedList.get(i);
					ebLinkedList.set(i,ebLinkedList.get(j));
					ebLinkedList.set(j,tmp);
				}
			}
		}
		
	}

	private void mapITCategoriesToEb(List<Eb> ebEntries) {
		for(Eb eb:ebEntries)
		{
			String catName=eb.getCatName();
			String ebCatCode=cacheService.getEbCategoryCode(catName);
			
			if(ebCatCode==null || ebCatCode.trim().equals(""))
				ebCatCode="177";//generic top level Computer & Networking category
			
			
			
			eb.setEbCode(ebCatCode);
			cacheService.putProdIDebCatCode(eb.getProdId(), ebCatCode);
		}
	}

	public ProductDao getProductDao()
	{
		return productDao;
	}

	public void setProductDao(ProductDao productDao)
	{
		this.productDao = productDao;
	}
	
	public EbMappingService getEbMappingService() {
		return ebMappingService;
	}

	public void setEbMappingService(EbMappingService ebMappingService) {
		this.ebMappingService = ebMappingService;
	}

	public CacheService getCacheService() {
		return cacheService;
	}

	public void setCacheService(CacheService cacheService) {
		this.cacheService = cacheService;
	}


}
